<template>
  <div class="app-container">
    <el-row class="margin-bottom">
      <el-select v-model="input.classloader" placeholder="选择一个类加载器" size="small" clearable filterable @change="handleChangeClassloader">
        <el-option v-for="cl in classloaders" :key="cl" :label="cl" :value="cl" />
      </el-select>
      <el-button class="margin-left" size="small" @click="dialog.single.visible = true">单文件上传</el-button>
      <el-button class="margin-left" size="small" @click="openMultiUploadDialog">多文件上传</el-button>
      <el-button class="margin-left" size="small" @click="openPomContentDialog">Pom 添加工件</el-button>
    </el-row>
    <el-row>
      <el-col :span="13">
        <el-table
          :data="loadedClasses"
          border
          stripe
          style="width: 100%"
          height="500"
          highlight-current-row
          size="mini"
          @row-click="selectClass"
        >
          <el-table-column type="index" width="55" />
          <el-table-column
            prop="className"
            :show-overflow-tooltip="true"
            label="类名"
            sortable
          />
          <el-table-column
            label="mc"
            width="60"
            prop="methods"
          />

          <el-table-column
            prop="fields"
            label="fc"
            width="60"
          />

        </el-table>
      </el-col>
      <el-col :span="11">
        <div class="padding-bottom padding-left">{{ sourceCode.className }}</div>
        <div style="height: 600px; overflow-y: scroll">
          <textarea ref="sourceCode" />
        </div>

      </el-col>
    </el-row>

    <!-- 单文件上传 -->
    <el-dialog :visible.sync="dialog.single.visible" width="50%" :title="dialog.single.title">
      <el-form ref="singleUploadForm" :rules="dialog.single.rules" inline size="mini" :model="dialog.single.data">
        <el-form-item prop="classloaderName">
          <el-select
            v-model="dialog.single.data.classloaderName"
            placeholder="选择类加载器或者新建"
            size="small"
            clearable
            filterable
            default-first-option
            allow-create
          >
            <el-option v-for="cl in classloaders" :key="cl" :label="cl" :value="cl" />
          </el-select>
        </el-form-item>

        <el-form-item prop="file">
          <el-upload
            ref="singleUpload"
            drag
            :auto-upload="false"
            action="#"
            :multiple="false"
            :limit="1"
            :on-change="singleUploadSetFiles"
            @on-exceed="uploadSingleLimit"
          >
            <i class="el-icon-upload" />
            <div class="el-upload__text">将文件拖到此处，或<em>点击上传</em></div>
            <div slot="tip" class="el-upload__tip">只能上传 class,java,zip,jar,xml 文件,且 xml 必须是 pom.xml </div>
          </el-upload>
        </el-form-item>
      </el-form>

      <span slot="footer" class="dialog-footer">
        <el-button class="" type="primary" size="small" :disabled="!dialog.single.data.classloaderName" @click="uploadSingle">确定上传</el-button>
      </span>
    </el-dialog>

    <!-- 多文件上传 -->
    <el-dialog :visible.sync="dialog.multi.visible" width="80%" :title="dialog.multi.title" v-loading="dialog.multi.loading">
      <el-form ref="multiUploadForm" :rules="dialog.multi.rules" size="mini" :model="dialog.multi.data">
        <el-form-item label="Maven Settings">
          <connect-chose module="maven" v-model="dialog.multi.data.settings"/>
        </el-form-item>
        <el-form-item prop="classloaderName">
          <el-select
            v-model="dialog.multi.data.classloaderName"
            placeholder="选择类加载器或者新建"
            size="small"
            clearable
            filterable
            default-first-option
            allow-create
          >
            <el-option v-for="cl in classloaders" :key="cl" :label="cl" :value="cl" />
          </el-select>
        </el-form-item>

        <el-form-item>
          <el-row>
            <el-col :span="8">
              <el-upload
                ref="multiUpload"
                :auto-upload="false"
                action="#"
                :multiple="true"
                :on-change="multiUploadSetFiles"
              >
                <el-button size="small" type="primary" :disabled="!dialog.multi.data.settings || !dialog.multi.data.classloaderName">点击上传</el-button>
              </el-upload>
            </el-col>
            <el-col :span="16">
              <textarea ref="multiPomTextArea" />
            </el-col>
          </el-row>

        </el-form-item>
      </el-form>

      <span slot="footer" class="dialog-footer">
        <el-button class="" type="primary" size="small" @click="uploadMulti">确定上传</el-button>
      </span>
    </el-dialog>

    <!-- pom 添加工件上传 -->
    <el-dialog :visible.sync="dialog.pom.visible" width="80%" :title="dialog.pom.title" v-loading="dialog.pom.loading">
      <el-form ref="pomForm" :rules="dialog.pom.rules" size="mini" :model="dialog.pom.data">
        <el-form-item label="Maven Settings">
          <connect-chose module="maven" v-model="dialog.pom.data.settings"/>
        </el-form-item>
        <el-form-item prop="classloaderName">
          <el-button class=" margin-right" type="primary" size="small" @click="uploadPomContent" :disabled="!dialog.pom.data.settings || !dialog.pom.data.classloaderName">确定</el-button>
          <el-select
            v-model="dialog.pom.data.classloaderName"
            placeholder="选择类加载器或者新建"
            size="small"
            clearable
            filterable
            default-first-option
            allow-create
          >
            <el-option v-for="cl in classloaders" :key="cl" :label="cl" :value="cl" />
          </el-select>
        </el-form-item>

        <el-form-item>
          <textarea ref="pomTextArea" />
        </el-form-item>
      </el-form>
    </el-dialog>

    <!-- 本次上传加载的信息 -->
    <el-dialog :visible.sync="dialog.uploadInfo.visible" width="80%" :title="dialog.uploadInfo.title" >
      <el-row>
        <el-col :span="12">
          <div>加载的 class 信息</div>
          <ul style="list-style-type: none;padding: 0">
            <li v-for="cl in dialog.uploadInfo.data.classes" :key="'loadClass_'+cl">{{ cl }}</li>
          </ul>
        </el-col>

        <el-col :span="12">
          <div>加载的 jar 信息</div>
          <ul style="list-style-type: none;padding: 0">
            <li v-for="jar in dialog.uploadInfo.data.jars" :key="'loadJar_'+jar">{{ jar }}</li>
          </ul>
        </el-col>
      </el-row>
    </el-dialog>
  </div>
</template>

<script>
import core from '../../../api/core'
import ConnectChose from '@/views/components/ConnectChose'

import 'mavon-editor/dist/css/index.css'
// 引入全局实例
import codeMirror from 'codemirror'
// 核心样式
import 'codemirror/lib/codemirror.css'
// 语法高亮
import 'codemirror/mode/clike/clike.js'
import 'codemirror/mode/xml/xml.js'
const CodeMirror = window.CodeMirror || codeMirror

const defaultPomContent = '<?xml version="1.0" encoding="UTF-8"?>\n' +
  '<project xmlns="http://maven.apache.org/POM/4.0.0"\n' +
'         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\n' +
'         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">\n' +
'    <modelVersion>4.0.0</modelVersion>\n' +
'\n' +
'    <groupId>org.example</groupId>\n' +
'    <artifactId>example</artifactId>\n' +
'    <version>1.0-SNAPSHOT</version>\n' +
'\n' +
'    <dependencies>\n' +
'        \n' +
'    </dependencies>\n' +
'\n' +
'</project>'

export default {
  name: 'classloader',
  components: { ConnectChose },
  data() {
    return {
      input: {
        classloader: null
      },
      classloaders: [],
      loadedClasses: [],
      dialog: {
        single: {
          visible: false,
          title: '上传单个文件',
          rules: {
            classloaderName: [{ required: true, message: '类加载器名称必填', trigger: 'blur' }],
            file: [{ required: true, message: '必须上传一个文件', trigger: 'blur' }]
          },
          data: {
            classloaderName: null,
            file: null
          }
        },
        multi: {
          editorCodeMirror: null,
          visible: false,
          title: '上传多个文件',
          rules: {
            classloaderName: [{ required: true, message: '类加载器名称必填', trigger: 'blur' }]
          },
          loading: false,
          data: {
            settings: null,
            classloaderName: null,
            files: [],
            pomContent: null
          }
        },
        pom: {
          editorCodeMirror: null,
          visible: false,
          title: '使用 pom 来添加工件',
          loading: false,
          data: {
            settings: null,
            classloaderName: null,
            pomContent: null
          },
          rules: {
            classloaderName: [{ required: true, message: '类加载器名称必填', trigger: 'blur' }]
          }
        },
        uploadInfo: {
          visible: false,
          title: '上传响应信息',
          data: {
            classes: [],
            jars: [],
            removeFiles: []
          }
        }
      },
      sourceCode: {
        className: null,
        content: '暂无代码',
        editorCodeMirror: null
      }
    }
  },
  mounted() {
    this.loadClassloaders()
    // 初始化代码编辑器
    this.initCodeMirror()
  },
  methods: {
    initCodeMirror() {
      // 初始化编辑器实例(查看源码)，传入需要被实例化的文本域对象和默认配置
      this.sourceCode.editorCodeMirror = CodeMirror.fromTextArea(this.$refs['sourceCode'], {
        mode: 'text/x-java', // 选择对应代码编辑器的语言
        tabSize: 4, // 缩进格式
        lineNumbers: true, // 显示行号
        line: true
      })
      this.sourceCode.editorCodeMirror.setSize('100%', '700px')// 设置编辑器大小
      this.sourceCode.editorCodeMirror.setValue('// no code')
    },
    uploadSingle() {
      this.$refs['singleUploadForm'].validate((valid) => {
        if (!valid) {
          return false
        }
        // console.log(this.dialog.single.data)
        const { classloaderName, file } = this.dialog.single.data
        const formData = new FormData()
        formData.append('file', file, file.name)
        formData.append('classloaderName', classloaderName)
        core.uploadSingle(classloaderName, formData).then(res => {
          this.dialog.single.visible = false
          this.loadClassloaders()
          this.$refs['singleUploadForm'].resetFields()

          this.dialog.uploadInfo.data = res.data
          this.dialog.uploadInfo.visible = true
        })
      })
    },
    uploadSingleLimit() {
      this.$message('只能上传一个文件')
    },
    singleUploadSetFiles(file, filelist) {
      this.dialog.single.data.file = file.raw
    },
    openPomContentDialog() {
      this.dialog.pom.visible = true
      this.$nextTick(() => {
        if (!this.dialog.pom.editorCodeMirror) {
          this.dialog.pom.editorCodeMirror = CodeMirror.fromTextArea(this.$refs['pomTextArea'], {
            mode: 'text/xml', // 选择对应代码编辑器的语言
            tabSize: 2, // 缩进格式
            lineNumbers: true, // 显示行号
            line: true
          })
        }

        this.dialog.pom.editorCodeMirror.setSize('100%', '700px')// 设置编辑器大小
        this.dialog.pom.editorCodeMirror.setValue(defaultPomContent)
      })
    },
    openMultiUploadDialog() {
      this.dialog.multi.visible = true
      this.$nextTick(() => {
        if (!this.dialog.multi.editorCodeMirror) {
          this.dialog.multi.editorCodeMirror = CodeMirror.fromTextArea(this.$refs['multiPomTextArea'], {
            mode: 'text/xml', // 选择对应代码编辑器的语言
            tabSize: 2, // 缩进格式
            lineNumbers: true, // 显示行号
            line: true
          })
        }

        this.dialog.multi.editorCodeMirror.setSize('100%', '700px')// 设置编辑器大小
        this.dialog.multi.editorCodeMirror.setValue(defaultPomContent)
      })
    },
    multiUploadSetFiles(file, filelist) {
      this.dialog.multi.data.files = filelist.map(file => file.raw)
    },
    uploadMulti() {
      this.$refs['multiUploadForm'].validate((valid) => {
        if (!valid) {
          return false
        }
        const pomContent = this.dialog.multi.editorCodeMirror.getValue()
        // console.log(this.dialog.multi.data)
        const { classloaderName, files } = this.dialog.multi.data
        const formData = new FormData()
        for (let i = 0; i < files.length; i++) {
          formData.append('files', files[i], files[i].name)
        }
        formData.append('classloaderName', classloaderName)
        formData.append('pomContent', pomContent)

        this.dialog.multi.loading = true
        core.uploadMulti(formData,this.dialog.multi.data.settings).then(res => {
          this.dialog.multi.visible = false
          this.loadClassloaders()
          this.$refs['multiUploadForm'].resetFields()

          this.dialog.uploadInfo.data = res.data
          this.dialog.uploadInfo.visible = true
          this.dialog.multi.loading = false
        }).catch(res => {
          this.dialog.multi.loading = false
        })
      })
    },
    uploadPomContent() {
      this.$refs['pomForm'].validate((valid) => {
        if (!valid) {
          return false
        }
        const pomContent = this.dialog.pom.editorCodeMirror.getValue()

        this.dialog.pom.loading = true
        core.uploadContent(this.dialog.pom.data.classloaderName, pomContent,this.dialog.pom.data.settings).then(res => {
          this.dialog.pom.visible = false
          this.loadClassloaders()
          this.$refs['pomForm'].resetFields()

          this.dialog.uploadInfo.data = res.data
          this.dialog.uploadInfo.visible = true
          this.dialog.pom.loading = false
        }).catch(res => {
          this.dialog.pom.loading = false
        })
      })
    },
    selectClass(row, column, event) {
      this.sourceCode.className = row.className
      core.deCompileClass(this.input.classloader, row.className).then(res => {
        // this.sourceCode.content = res.data;
        this.sourceCode.editorCodeMirror.setValue(res.data)
      })
    },
    handleChangeClassloader(cl) {
      this.input.classloader = cl
      core.listLoadedClasses(cl).then(res => {
        this.loadedClasses = res.data
      })
    },
    loadClassloaders() {
      core.classloaders().then(res => {
        this.classloaders = res.data
        if (res.data && res.data.length > 0) {
          this.handleChangeClassloader(res.data[0])
        }
      })
    }
  }
}
</script>

